package com.wzs.rpc.server.tcp;

import com.wzs.rpc.model.RpcRequest;
import com.wzs.rpc.model.RpcResponse;
import com.wzs.rpc.protocol.ProtocolMessage;
import com.wzs.rpc.protocol.ProtocolMessageDecoder;
import com.wzs.rpc.protocol.ProtocolMessageEncoder;
import com.wzs.rpc.protocol.ProtocolMessageTypeEnum;
import com.wzs.rpc.registry.LocalRegistry;
import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetSocket;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.Method;

@Slf4j
public class TcpServerHandler implements Handler<NetSocket> {
    @Override
    public void handle(NetSocket socket) {
        // 获取客户端地址并打印
        String clientAddress = socket.remoteAddress().toString();
        log.info("New client connected: {}", clientAddress);

        TcpBufferHandlerWrapper tcpBufferHandlerWrapper = new TcpBufferHandlerWrapper(buffer -> {
            ProtocolMessage<RpcRequest> protocolMessage;
            try {
                protocolMessage = (ProtocolMessage<RpcRequest>) ProtocolMessageDecoder.decode(buffer);
            } catch (IOException e) {
                log.error("协议消息解码错误", e);
                throw new RuntimeException("协议消息解码错误", e);
            }
            RpcResponse rpcResponse = new RpcResponse();
            RpcRequest rpcRequest = protocolMessage.getBody();
            log.info("Received rpcRequest from client {}: {}", clientAddress, rpcRequest);
            if (rpcRequest == null || rpcRequest.getServiceName() == null || rpcRequest.getMethodName() == null) {
                rpcResponse.setMessage("rpcRequest 或其关键字段为空");
                doResponse(protocolMessage, rpcResponse, socket);
                return;
            }

            try {
                // 获取要调用的服务实现类，通过反射调用
                Class<?> clz = LocalRegistry.get(rpcRequest.getServiceName());
                Method method = clz.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
                Object result = method.invoke(clz.getConstructor().newInstance(), rpcRequest.getArgs());
                // 封装返回结果
                rpcResponse.setData(result);
                rpcResponse.setDataType(method.getReturnType());
                rpcResponse.setMessage("ok");
            } catch (Exception e) {
                log.error("服务执行失败, rpcRequest is {}", rpcRequest, e);
                rpcResponse.setMessage(e.getMessage());
                rpcResponse.setException(e);
            }
            doResponse(protocolMessage, rpcResponse, socket);
        });
        socket.handler(tcpBufferHandlerWrapper);
    }

    private void doResponse(ProtocolMessage<RpcRequest> rpcRequestProtocolMessage, RpcResponse rpcResponse, NetSocket socket) {
        ProtocolMessage.Header header = rpcRequestProtocolMessage.getHeader();
        header.setType((byte)ProtocolMessageTypeEnum.RESPONSE.getCode());
        ProtocolMessage<RpcResponse> rpcResponseProtocolMessage = new ProtocolMessage<>(header, rpcResponse);
        try {
            Buffer buffer = ProtocolMessageEncoder.encode(rpcResponseProtocolMessage);
            socket.write(buffer);
        } catch (Exception e) {
            log.error("协议消息编码错误", e);
            throw new RuntimeException("协议消息编码错误", e);
        }
    }
}
